﻿/**	lolix_lib.h
 *	----	Create Time Stamp	--2008-07-06 02:08:39--
 *------------------------------------------------------------------------------
 *	Mean	:
 *	Author	:Nick Shallery	(nicknide@gmail.com)
 *	Version	:1.0.5.5	(2009-11-13 19:40:02)
 *------------------------------------------------------------------------------
**/	/*YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.*/

#if			!defined(__LOLIX_X__LOLIX_LIB__NICK__K_IN_G__)
#define		__LOLIX_X__LOLIX_LIB__NICK__K_IN_G__
//==============================================================================
//--------------------------------------------------------------------------

#if			defined(WIN32)

#if			!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
	#include	"./lolix_macro.h"
#endif	//	!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)

#if			!defined(__LOLIX__LOLIX_ERR__K_IN_G__)
	#include	"./lolix_err.h"
#endif	//	!defined(__LOLIX__LOLIX_ERR__K_IN_G__)

#if			!defined(__LOLIX__TOY__STD_ALGORITHM__NICK__K_IN_G__)
	#include	"./toy/std_algorithm.hpp"
#endif	//	!defined(__LOLIX__TOY__STD_ALGORITHM__NICK__K_IN_G__)

#if			!defined(_WINDOWS_)
	#include	<windows.h>
#endif	//	!defined(_WINDOWS_)


namespace
{
	class lolix_lib
	{
		CANNT_COPY_LOLI;
		HMODULE				_lib;
		lolix::fnLxLoadInst		_lxLoadInst;
		lolix::fnLxFreeLib		_lxFreeLib;

	public:
		LOLIX_INLINE_CALL	lolix_lib(void)
			: _lib(0)
			, _lxLoadInst(&__lxLoadInst_Null)
			, _lxFreeLib(&__lxFreeLib_Null)
		{
		}

		LOLIX_INLINE_CALL	~lolix_lib(void)
		{
			if ( !_lib )
				return;
			__FreeLib();
		}

		LOLIX_INLINE_CALL	lolix::LOLIX_RETNV	load(const wchar_t* wcsFile)
		{
			__Clear();
			_lib = ::LoadLibraryW(wcsFile);
			if ( !_lib )
				return lolix::LOLIX_ERROR_INVALID_FILE;
			return __LoadProc();
		}

		LOLIX_INLINE_CALL	void		unload(void)
		{
			__Clear();
		}


		LOLIX_INLINE_CALL	lolix::LOLIX_RETNV	lxLoadInst(lolix::lolix_inst** out_ptr, const lolix::lolix_init_param* in_param)
		{
			return _lxLoadInst(out_ptr, in_param);
		}


		LOLIX_INLINE_CALL	void swap(lolix_lib& o)
		{
			lolix::swap(_lib, o._lib);
			lolix::swap(_lxLoadInst, o._lxLoadInst);
			lolix::swap(_lxFreeLib, o._lxFreeLib);
		}

	private:
		LOLIX_INLINE_CALL	void	__Clear(void)
		{
			if ( !_lib )
				return;

			__FreeLib();
			_lxLoadInst = &lolix_lib::__lxLoadInst_Null;
			_lxFreeLib = &lolix_lib::__lxFreeLib_Null;
			_lib = 0;
		}

		LOLIX_INLINE_CALL	void	__FreeLib(void)
		{
			if ( LOLIX_IS_ERROR(_lxFreeLib()) )
				::FreeLibrary(_lib);
		}

		LOLIX_INLINE_CALL	lolix::LOLIX_RETNV	__LoadProc(void)
		{
			do
			{
				(PROC&)_lxLoadInst = ::GetProcAddress(_lib, "lxLoadInst");
				if ( !_lxLoadInst )
					break;
				_lxFreeLib = (lolix::fnLxFreeLib)::GetProcAddress(_lib, "lxFreeLib");
				if ( !_lxFreeLib )
					break;
				return lolix::LOLIX_RETNV_OK;
			}while(0);
			__Clear();
			return lolix::LOLIX_ERROR_INVALID_RESOURCE;
		}


		static lolix::LOLIX_RETNV	LOLIX_STD_CALL __lxLoadInst_Null(lolix::lolix_inst** /*out_ptr*/, const lolix::lolix_init_param* /*in_param*/)
		{
			return lolix::LOLIX_ERROR_INVALID_INTERFACE;
		}
		static lolix::LOLIX_RETNV	LOLIX_STD_CALL __lxLoadPlugin_Null(lolix::lolix_inst* lx_inst, lolix::lolix_plugin_param const*const plugin_param)
		{
			return lolix::LOLIX_ERROR_INVALID_INTERFACE;
		}
		static lolix::LOLIX_RETNV	LOLIX_STD_CALL __lxFreeLib_Null(void)
		{
			return lolix::LOLIX_ERROR_UNSUPPORT_INTERFACE;
		}

	};
}
#endif	//	defined(WIN32)


namespace lolix{
	void swap(lolix_lib& l, lolix_lib& r)
	{
		l.swap(r);
	}
}

//--------------------------------------------------------------------------
//==============================================================================
#endif	//	!defined(__LOLIX_X__LOLIX_LIB__NICK__K_IN_G__)
